(function(l, d) {
    "object" === typeof exports && "undefined" !== typeof module ? d() : "function" === typeof define && define.amd ? define(d) : d()
})(this, function() {
    var l = "function" === typeof Symbol && "symbol" === typeof Symbol.iterator ? function(d) {
        return typeof d
    } : function(d) {
        return d && "function" === typeof Symbol && d.constructor === Symbol && d !== Symbol.prototype ? "symbol" : typeof d
    };
    (function(d, h) {
        function K(a) {
            a = d.extend({}, u, a || {});
            null === n && (n = d("body"));
            for (var b = d(this), c = 0, f = b.length; c < f; c++) L(b.eq(c), a);
            return b
        }

        function L(a,
            b) {
            if (!a.hasClass("autocompleter-node")) {
                b = d.extend({}, b, a.data("autocompleter-options"));
                "string" !== typeof b.source || ".json" !== b.source.slice(-5) && !0 !== b.asLocal || d.ajax({
                    url: b.source,
                    type: "POST",
                    dataType: "json",
                    async: !1
                }).done(function(a) {
                    b.source = a
                });
                var c = '<div class="autocompleter  ' + b.customClass.join(" ") + '" id="autocompleter-' + (z + 1) + '">';
                b.hint && (c += '<div class="autocompleter-hint"></div>');
                c += '<ul class="autocompleter-list"></ul></div>';
                a.addClass("autocompleter-node");
                d("body").append(c);
                c = d(".autocompleter").eq(0);
                c.css({
                    width: b.width,
                    top: a.offset().top + a.get(0).offsetHeight,
                    left: a.offset().left
                });
                var f = a.attr("autocomplete");
                a.attr("autocomplete", "off");
                a = d.extend({
                    $node: a,
                    $autocompleter: c,
                    $selected: null,
                    $list: null,
                    index: -1,
                    hintText: !1,
                    source: !1,
                    jqxhr: !1,
                    response: null,
                    focused: !1,
                    query: "",
                    originalAutocomplete: f,
                    guid: z++
                }, b);
                a.$autocompleter.on("mousedown.autocompleter", ".autocompleter-item", a, A).data("autocompleter", a);
                a.$node.on("keyup.autocompleter", a, M).on("keydown.autocompleter",
                    a, N).on("focus.autocompleter", a, O).on("blur.autocompleter", a, P).on("mousedown.autocompleter", a, Q)
            }
        }

        function R(a, b, c) {
            var d = [];
            a = a.toUpperCase();
            if (b.length)
                for (var e = 0; 2 > e; e++)
                    for (var g in b)
                        if (d.length < c.limit) {
                            var h = c.customLabel && b[g][c.customLabel] ? b[g][c.customLabel] : b[g].label;
                            switch (e) {
                                case 0:
                                    0 === h.toUpperCase().search(a) && (d.push(b[g]), delete b[g]);
                                    break;
                                case 1:
                                    -1 !== h.toUpperCase().search(a) && (d.push(b[g]), delete b[g])
                            }
                        }
            return d
        }

        function v(a) {
            clearTimeout(B);
            a.query = d.trim(a.$node.val());
            !a.empty && 0 === a.query.length || a.minLength && a.query.length < a.minLength ? p(a) : a.delay ? B = setTimeout(function() {
                C(a)
            }, a.delay) : C(a)
        }

        function D(a) {
            return Object.keys(a).map(function(b) {
                return encodeURIComponent(b) + "=" + encodeURIComponent(a[b])
            }).join("&")
        }

        function E(a) {
            var b = a.getFullYear(),
                c = a.getMonth() + 1;
            a = a.getDate();
            return b + "" + c + a
        }

        function C(a) {
            if ("object" === l(a.source)) {
                p(a);
                var b = R(a.query, S(a.source), a);
                b.length && q(b, a)
            } else {
                a.jqxhr && a.jqxhr.abort();
                var c = {
                    limit: a.limit,
                    query: a.query
                };
                "function" ===
                typeof a.combine && (c = a.combine(c));
                a.jqxhr = d.ajax({
                    url: a.source,
                    type: "POST",
                    dataType: "json",
                    data: c,
                    beforeSend: function(b) {
                        a.$autocompleter.addClass("autocompleter-ajax");
                        p(a);
                        if ("" == d.trim(c.q)) {
                            var e = localStorage.SearchKey,
                                f = c.scene;
                            e = null == e || void 0 == e ? {} : JSON.parse(e);
                            e.hasOwnProperty(f) && 0 < e[f].length && b.abort() && q({
                                state: 1,
                                list: e[f],
                                SearchKey: !0
                            }, a)
                        } else a.cache && ((e = this.url + "?" + D(c)) ? (f = r[e]) && f.value ? (e = f.value, e = E(new Date) != E(new Date(f.timestamp)) ? !1 : e) : e = !1 : e = !1, e && (b.abort(), q(e, a)))
                    }
                }).done(function(b) {
                    if (a.offset) {
                        var d =
                            a.offset;
                        for (d = d.split("."); b && d.length;) b = b[d.shift()]
                    }
                    if (a.cache && (d = this.url + "?" + D(c), F && d && b)) {
                        r[d] = {
                            value: b,
                            timestamp: +new Date
                        };
                        try {
                            localStorage.setItem("autocompleterCache", JSON.stringify(r))
                        } catch (g) {
                            if (22 === (g.code || g.number || g.message)) w();
                            else throw g;
                        }
                    }
                    q(b, a)
                }).always(function() {
                    a.$autocompleter.removeClass("autocompleter-ajax")
                })
            }
        }

        function p(a) {
            a.response = null;
            a.$list = null;
            a.$selected = null;
            a.index = 0;
            a.$autocompleter.find(".autocompleter-list").empty();
            a.$autocompleter.find(".autocompleter-hint").removeClass("autocompleter-hint-show").empty();
            a.hintText = !1;
            k(null, a)
        }

        function q(a, b) {
            T(a, b);
            b.$autocompleter.hasClass("autocompleter-focus") && x(null, b)
        }

        function T(a, b) {
            if (1 != a.state) return !1;
            for (var c = "", f = a.list, e = 0, g = f.length; e < g; e++) {
                var h = ["autocompleter-item"],
                    k = new RegExp(b.query, "gi");
                b.selectFirst && 0 === e && !b.changeWhenSelect && h.push("autocompleter-item-selected");
                var m = b.customLabel && f[e][b.customLabel] ? f[e][b.customLabel] : f[e].label,
                    l = m;
                m = b.highlightMatches ? m.replace(k, "<strong>$&</strong>") : m;
                c = (k = b.customValue && f[e][b.customValue] ?
                    f[e][b.customValue] : f[e].value) ? c + ('<li data-value="' + k + '" data-label="' + l + '" class="' + h.join(" ") + '">' + m + "</li>") : c + ('<li data-label="' + l + '" class="' + h.join(" ") + '">' + m + "</li>")
            }
            f.length && b.hint && (e = b.customLabel && f[0][b.customLabel] ? f[0][b.customLabel] : f[0].label, (g = e.substr(0, b.query.length).toUpperCase() === b.query.toUpperCase() ? e : !1) && b.query !== e && (e = g.replace(new RegExp(b.query, "i"), "<span>" + b.query + "</span>"), b.$autocompleter.find(".autocompleter-hint").addClass("autocompleter-hint-show").html(e),
                b.hintText = e));
            a.SearchKey && (c += '<li data-label="SearchKey" class="SearchKey ' + h.join(" ") + '">\u641c\u7d22\u8bb0\u5f55<a href="javascript:void(0);">\u6e05\u9664</a></li>');
            b.response = f;
            b.$autocompleter.find(".autocompleter-list").html(c);
            b.$selected = b.$autocompleter.find(".autocompleter-item-selected").length ? b.$autocompleter.find(".autocompleter-item-selected") : null;
            b.$list = f.length ? b.$autocompleter.find(".autocompleter-item") : null;
            b.index = b.$selected ? b.$list.index(b.$selected) : -1;
            b.$autocompleter.find(".autocompleter-item").each(function(a,
                c) {
                d(c).data(b.response[a])
            })
        }

        function M(a) {
            var b = a.data;
            a = a.keyCode ? a.keyCode : a.which;
            if (40 !== a && 38 !== a || !b.$autocompleter.hasClass("autocompleter-show")) - 1 === d.inArray(a, U) && -1 === d.inArray(a, b.ignoredKeyCode) && v(b);
            else {
                var c = b.$list.length;
                if (c) {
                    if (1 < c)
                        if (b.index === c - 1) {
                            var f = b.changeWhenSelect ? -1 : 0;
                            c = b.index - 1
                        } else 0 === b.index ? (f = b.index + 1, c = b.changeWhenSelect ? -1 : c - 1) : -1 === b.index ? (f = 0, --c) : (f = b.index + 1, c = b.index - 1);
                    else -1 === b.index ? c = f = 0 : f = c = -1;
                    b.index = 40 === a ? f : c;
                    b.$list.removeClass("autocompleter-item-selected"); - 1 !== b.index && b.$list.eq(b.index).addClass("autocompleter-item-selected");
                    b.$selected = b.$autocompleter.find(".autocompleter-item-selected").length ? b.$autocompleter.find(".autocompleter-item-selected") : null;
                    b.changeWhenSelect && y(b)
                }
            }
        }

        function N(a) {
            var b = a.data,
                c = a.keyCode ? a.keyCode : a.which;
            40 === c || 38 === c ? (a.preventDefault(), a.stopPropagation()) : 39 === c ? b.hint && b.hintText && b.$autocompleter.find(".autocompleter-hint").hasClass("autocompleter-hint-show") && (a.preventDefault(), a.stopPropagation(), a = b.$autocompleter.find(".autocompleter-item").length ?
                b.$autocompleter.find(".autocompleter-item").eq(0).attr("data-label") : !1) && (b.query = a, y(b), G(b), v(b)) : 13 === c && b.$autocompleter.hasClass("autocompleter-show") && b.$selected && A(a)
        }

        function O(a, b) {
            if (!b) {
                var c = a.data;
                c.$autocompleter.addClass("autocompleter-focus");
                c.$node.prop("disabled") || c.$autocompleter.hasClass("autocompleter-show") || !c.focusOpen || (v(c), c.focused = !0, setTimeout(function() {
                    c.focused = !1
                }, 500))
            }
        }

        function P(a, b) {
            a.preventDefault();
            a.stopPropagation();
            var c = a.data;
            b || (c.$autocompleter.removeClass("autocompleter-focus"),
                k(a))
        }

        function Q(a) {
            if ("mousedown" !== a.type || -1 === d.inArray(a.which, [2, 3])) {
                var b = a.data;
                !b.$list || b.focused || b.$node.is(":disabled") || (H && !V ? (a = b.$select[0], h.document.createEvent ? (b = h.document.createEvent("MouseEvents"), b.initMouseEvent("mousedown", !1, !0, h, 0, 0, 0, 0, 0, !1, !1, !1, !1, 0, null), a.dispatchEvent(b)) : a.fireEvent && a.fireEvent("onmousedown")) : b.$autocompleter.hasClass("autocompleter-closed") ? x(a) : b.$autocompleter.hasClass("autocompleter-show") && k(a))
            }
        }

        function x(a, b) {
            a = a ? a.data : b;
            !a.$node.prop("disabled") &&
                !a.$autocompleter.hasClass("autocompleter-show") && a.$list && a.$list.length && (a.$autocompleter.removeClass("autocompleter-closed").addClass("autocompleter-show"), n.on("click.autocompleter-" + a.guid, ":not(.autocompleter-item)", a, W))
        }

        function W(a) {
            d(a.target).hasClass("autocompleter-node") || 0 === d(a.currentTarget).parents(".autocompleter").length && k(a)
        }

        function k(a, b) {
            a = a ? a.data : b;
            a.$autocompleter.hasClass("autocompleter-show") && (a.$autocompleter.removeClass("autocompleter-show").addClass("autocompleter-closed"),
                n.off(".autocompleter-" + a.guid))
        }

        function A(a) {
            if ("mousedown" !== a.type || -1 === d.inArray(a.which, [2, 3])) {
                var b = a.data;
                a.preventDefault();
                a.stopPropagation();
                "mousedown" === a.type && d(this).length && (b.$selected = d(this), b.index = b.$list.index(b.$selected));
                b.$node.prop("disabled") || (k(a), y(b), G(b), p(b), "click" === a.type && b.$node.trigger("focus", [!0]))
            }
        }

        function y(a) {
            a.$selected ? (a.hintText && a.$autocompleter.find(".autocompleter-hint").hasClass("autocompleter-hint-show") && a.$autocompleter.find(".autocompleter-hint").removeClass("autocompleter-hint-show"),
                a.$selected.hasClass("SearchKey") ? w("SearchKey") : a.$node.val(a.$selected.attr("data-value") ? a.$selected.attr("data-value") : a.$selected.attr("data-label"))) : (a.hintText && !a.$autocompleter.find(".autocompleter-hint").hasClass("autocompleter-hint-show") && a.$autocompleter.find(".autocompleter-hint").addClass("autocompleter-hint-show"), a.$node.val(a.query))
        }

        function G(a) {
            a.callback.call(a.$autocompleter, a.$node.val(), a.index, a.response[a.index]);
            a.$node.trigger("change")
        }

        function I() {
            if (F) return JSON.parse(localStorage.getItem("autocompleterCache") ||
                "{}")
        }

        function w(a) {
            try {
                localStorage.removeItem(a || "autocompleterCache"), r = I()
            } catch (b) {
                throw b;
            }
        }

        function S(a) {
            if (null === a || "object" !== ("undefined" === typeof a ? "undefined" : l(a))) return a;
            var b = a.constructor();
            for (var c in a) a.hasOwnProperty(c) && (b[c] = a[c]);
            return b
        }
        var z = 0,
            U = [9, 13, 17, 19, 20, 27, 33, 34, 35, 36, 37, 39, 44, 92, 113, 114, 115, 118, 119, 120, 122, 123, 144, 145],
            X = "source empty limit cache cacheExpires focusOpen selectFirst changeWhenSelect highlightMatches ignoredKeyCode customLabel customValue template offset combine callback minLength delay".split(" "),
            J = h.navigator.userAgent || h.navigator.vendor || h.opera,
            Y = /Firefox/i.test(J),
            H = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(J),
            V = Y && H,
            n = null,
            B = null,
            F = function() {
                var a = "undefined" !== typeof h.localStorage;
                if (a) try {
                    localStorage.setItem("autocompleter", "autocompleter"), localStorage.removeItem("autocompleter")
                } catch (b) {
                    a = !1
                }
                return a
            }(),
            u = {
                source: null,
                asLocal: !1,
                empty: !0,
                limit: 10,
                minLength: 0,
                delay: 300,
                customClass: [],
                cache: !0,
                cacheExpires: 86400,
                focusOpen: !0,
                hint: !1,
                selectFirst: !1,
                changeWhenSelect: !0,
                highlightMatches: !1,
                ignoredKeyCode: [],
                customLabel: !1,
                customValue: !1,
                template: !1,
                offset: !1,
                width: 300,
                combine: null,
                callback: d.noop
            },
            t = {
                defaults: function(a) {
                    u = d.extend(u, a || {});
                    return "object" === l(this) ? d(this) : !0
                },
                option: function(a) {
                    return d(this).each(function(b, c) {
                        b = d(c).next(".autocompleter").data("autocompleter");
                        for (var f in a) - 1 !== d.inArray(f, X) && (b[f] = a[f])
                    })
                },
                open: function() {
                    return d(this).each(function(a, b) {
                        (a = d(b).next(".autocompleter").data("autocompleter")) && x(null, a)
                    })
                },
                close: function() {
                    return d(this).each(function(a,
                        b) {
                        (a = d(b).next(".autocompleter").data("autocompleter")) && k(null, a)
                    })
                },
                clearCache: function() {
                    w()
                },
                destroy: function() {
                    return d(this).each(function(a, b) {
                        if (a = d(".autocompleter").data("autocompleter")) a.jqxhr && a.jqxhr.abort(), a.$autocompleter.hasClass("open") && a.$autocompleter.find(".autocompleter-selected").trigger("click.autocompleter"), a.originalAutocomplete ? a.$node.attr("autocomplete", a.originalAutocomplete) : a.$node.removeAttr("autocomplete"), a.$node.off(".autocompleter").removeClass("autocompleter-node"),
                            a.$autocompleter.off(".autocompleter").remove()
                    })
                }
            },
            r = I();
        d.fn.autocompleter = function(a) {
            return t[a] ? t[a].apply(this, Array.prototype.slice.call(arguments, 1)) : "object" !== ("undefined" === typeof a ? "undefined" : l(a)) && a ? this : K.apply(this, arguments)
        };
        d.autocompleter = function(a) {
            "defaults" === a ? t.defaults.apply(this, Array.prototype.slice.call(arguments, 1)) : "clearCache" === a && t.clearCache.apply(this, null)
        }
    })(jQuery, window)
});